iT邦幫忙

2025 iThome 鐵人賽

DAY 3
0

在開始討論pyproject.toml這個配置檔案之前,我們先回顧一下Python在專案設定檔案的混沌時期,是怎麼演進的。

從混亂開始:setup.py 與 requirements.txt 的年代

在早期的Python 2 和 Python 3初期,常會看到的專案結構可能長下面這樣:

myproject/
 ├─ setup.py
 ├─ setup.cfg
 ├─ requirements.txt
 ├─ MANIFEST.in
 ├─ tox.ini
 ├─ .flake8
 └─ ...
  • setup.py:記錄專案的安裝資訊,但必須用 Python 程式碼撰寫,語法容易出錯。
  • requirements.txt:只是一個套件清單,沒辦法表達「建置」或「發佈」需求。
  • setup.cfg / tox.ini / .flake8:每個工具要自己一份設定檔,專案根目錄變得一團亂。

然而我在這時期看到了requirements.txt這個檔案。

當時的我第一個反應是:「這也太陽春了吧!」

在 Java 世界,我早就習慣了 Maven/Gradle;在 .NET 世界,NuGet 也有完整的套件描述檔與工具鏈。這些工具不僅能管理依賴,還能處理建置、測試、部署,一條龍服務。

反觀 Python 世界,竟然只丟給我一個 requirements.txt,還是純文字清單。如果今天專案只是小工具或小腳本,這也許勉強能接受;但一旦要做企業級專案,這樣的專案管理方式簡直就是夢魘於是,Python 社群開始尋求更現代化的解決方案。

PEP 518:統一的希望

直到後來2016 年,PEP 518 的提出,,帶來了 pyproject.toml。這就像是 Python 世界終於補上了和 Maven、NuGet 同一層級的基礎設施。從此之後,我終於不必再看著一堆分散的 .cfg.ini,心裡暗罵「這到底是什麼拼裝車」了。

它的使命很明確:

  • 統一建置方式:不用再硬寫 setup.py
  • 集中工具設定:不同工具都能寫進同一個檔案。
  • 讓專案更乾淨:不再有一堆零散的 .cfg.ini

從這一刻開始,pyproject.toml 逐漸成為 現代 Python 專案的「心臟」。所以當你看到還有人單純依賴 requirements.txt,你就可以跟他分享 pyproject.toml 帶來的更完整方案。

第一步:最小的 pyproject.toml

[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"

這段意思是:

  • requires:建置專案時需要安裝的套件
  • build-backend:指定誰來負責打包與建置(這裡是 setuptools

光這樣,就能取代舊時代的 setup.py

更進一步:工具設定整合

[tool.black]
line-length = 88
target-version = ["py310"]

[tool.isort]
profile = "black"

[tool.mypy]
ignore_missing_imports = true
strict = true

這意味著:

  • 你不需要再有 .flake8mypy.inipyproject.cfg
  • 專案根目錄瞬間清爽,所有設定都在一個檔案裡

requirements.txt 還需要嗎?

但你肯定有疑惑,我常在一個專案看到pyproject.tomlrequirements.txt這兩個檔案都存在欸,這到底是怎麼一回事?

不是說好有了pyproject.toml就不用requirements.txt了嗎?

其實並不是,而是必須 看情境

  • 發佈套件pyproject.toml 必須存在
  • 部署服務 / CI/CDrequirements.txt 仍然常見,因為它適合鎖定版本

也就是說其實,pyproject.toml的出現是為了補強requirements.txt所做不到的事情,因此在同一個專案底下可以常見到這兩個檔案並存。

心裡吶喊:我什麼時候可以捨棄requirements.txt掉這個檔案?

這時候一個燈兩個燈三個燈四個燈五個燈,終於千呼萬喚Hatch,可以登場了。因為Hatch的設計讓你在大部分情境下不需要再維護requirements.txt這個檔案。這時候我們的pyproject.toml這個檔案可以像下面這樣撰寫

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "my-awesome-project"
version = "0.1.0"
dependencies = [
    "requests>=2.28",
    "pydantic>=2.0"
]

[tool.hatch.envs.default]
dependencies = [
    "pytest",
    "black"
]

[tool.hatch.envs.dev]
dependencies = ["pytest", "black", "mypy"]

[tool.hatch.envs.docs]
dependencies = ["mkdocs", "mkdocs-material"]

你有看到這個檔案的寫法完全不一樣了:

  • [build-system]這裡引用的是Hatch來進行編譯的工具
  • [project] 定義了版本資訊以及依賴的套件
  • [tool.hatch.envs] 可以依照你要的環境來切分所需要的不同設定與依賴套件

結論

回顧一下這段歷程:

  • 從一開始 setup.pyrequirements.txtsetup.cfg 到處散落,專案根目錄像是拼裝車一樣。
  • 到了 PEP 518 的出現,pyproject.toml 統一了建置與工具設定,讓專案開始「有秩序」。
  • 再到 Hatch、Poetry 等新世代工具的登場,pyproject.toml 不再只是「輔助」,而是 專案的核心中樞

對我來說,這是一個從「混亂 → 整合 → 優雅」的演進過程。

如果你今天開始一個新的 Python 專案,沒有理由不使用pyproject.toml

然而Hatch的好處不只這樣,它還能徹底改變我們管理虛擬環境與專案依賴的方式。在 Day 5,我會帶大家實際操作 Hatch,看看它怎麼讓環境管理變得更簡單、更優雅。

但在這之前我們會先在Day 4來談論一下「專案目錄結構:從腳本到可維護的專案設計 」。

從 requirements.txt 到 pyproject.toml,是 Python 工程化的必經之路。我們明天見


上一篇
Day 2 - Python 環境管理:venv、conda 與 hatch 的選擇
下一篇
Day 4 - 專案目錄結構:從腳本到可維護的專案設計
系列文
30 天 Python 專案工坊:環境、結構、測試到部署全打通29
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言